package org.ecpkn.PAGridSim.NodeScalingOptimization;

import org.ecpkn.PAGridSim.core.configuration.Configuration;
import org.ecpkn.PAGridSim.core.configuration.Configuration.Const;
import org.ecpkn.PAGridSim.core.gridsimEntity.paMachine.PAMachine;
import org.ecpkn.PAGridSim.core.offlineOptimization.OfflineOptimizationAlgo;
import org.ecpkn.PAGridSim.core.offlineOptimization.OptimizedResultEntry;

public class NodeScalingOptimization extends OfflineOptimizationAlgo {
	public NodeScalingOptimization(double workload) {
		super(workload);
	}

	public OptimizedResultEntry optimize() throws Exception {
		int startNum = (int) workload_ + 1;
		double startFrequency = workload_ / startNum * PAMachine.MAXRATING;
		double alfa = startFrequency
				* Math.pow(2 * PAMachine.COEFFICIENT / PAMachine.POWERSTATIQUE,
						1.0 / 3);

		int scalingNum = (int) Math.ceil(startNum * alfa);
		if(scalingNum>Configuration.getInstance().getParameterInt(Configuration.Const.TOTAL_NODE_NUMBER)){
				throw new Exception(
						"NodeScalingOptimization.optimize:the optimized node number is greater than the total node number.Please add total number or decrease the workload");
		}
		// TODO:if si she wu ru, the optF should be recalculated
		double optFrequency = (alfa == 0 ? 0 : startFrequency / alfa);
		double optUtilization = (scalingNum == 0 ? 0 : workload_ / scalingNum
				* PAMachine.MAXRATING / optFrequency);
		OptimizedResultEntry optRE = new OptimizedResultEntry(optUtilization,
				optFrequency, scalingNum);
		int totalNodeNum = Configuration.getInstance().getParameterInt(
				Const.TOTAL_NODE_NUMBER);
		// OptimizedResultEntry optRE = new
		// OptimizedResultEntry(workload_/totalNodeNum,
		// PAMachine.MAXRATING, totalNodeNum);
		/*
		 * OptimizedResultEntry optRE = new
		 * OptimizedResultEntry(workload_/totalNodeNum, PAMachine.MAXRATING,
		 * totalNodeNum);
		 */
		return optRE;
	}
}
